<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2018 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Released under the MIT License.
// +----------------------------------------------------------------------
// | Author: 老猫 <thinkcmf@126.com>
// +----------------------------------------------------------------------

namespace app\api\controller;

use think\request;
use think\Db;
use cmf\controller\HomeBaseController;

class CallbackController extends HomeBaseController
{

    /**
    *
    *回调地址
    **/
    public function payBack()
    {
        WL([ 'msg' => '----判断回调111-----'],'wx_pay');
        //接收数据，检测数据
        //$data = $this->request->param();
        $data = file_get_contents("php://input");
    
        //转成数组
        $data = json_decode(json_encode(simplexml_load_string($data,'SimpleXMLElement',LIBXML_NOCDATA)),true);

        WL([ 'msg' => $data],'wx_pay');
        if(!empty($data))
        {

            WL([ 'msg' => '开始处理回调订单'],'wx_pay');
            //判断结果
            if($data['return_code'] != 'SUCCESS')
            {
                WL([ 'msg' => '回调结果未成功', 'return_code' => $data['return_code'], 'return_msg' => $data['return_msg']],'wx_pay');
                return;
            }

            WL([ 'msg' => '----校验签名-----'],'wx_pay');
            //----------------------校验签名------------------------------
            //保存微信服务器返回的签名sign
            $data_sign = $data['sign'];
            //sign不参与签名算法
            unset($data['sign']);
            //生成签名
            $sign2 = $this->getSign2($data);
            if($sign2 != $data_sign)
            {
                WL([ 'msg' => '签名有误', 'data_sign' => $data_sign, 'sign2' => $sign2],'wx_pay');
                return;
            }


            WL([ 'msg' => '订单正常付款，开始修改订单状态'],'wx_pay');
            //付款成功，进行数据处理
            $courseModel = new \app\home\model\CourseModel();
            $orderModel = new \app\home\model\OrdersModel();
            $coursecodeModel = new \app\home\model\CourseCodeModel();

            $order_number = $data['out_trade_no'];

            WL([ 'order_number' => $order_number],'wx_pay');
            $order_info = $orderModel->checkMemberOrders($order_number);

            WL([ 'msg' => '查找订单'],'wx_pay');
            if(empty($order_info))
            {
                WL([ 'msg' => '不存在的用户订单', 'order_number' => $order_number],'wx_pay');
                return;
            }


            WL([ 'msg' => $order_info],'wx_pay');
            //查看订单状态,如果已经是付款状态。就不需要再操作
            if($order_info['status'] != 0)
            {
                WL([ 'msg' => '该账单状态已被改变', 'order_number' => $order_number],'wx_pay');
                return;
            }


            WL([ 'msg' => '订单金额对比'],'wx_pay');
            //订单金额
            $money = $data['total_fee'] / 100;
            if($order_info['pay_money'] != $money)
            {
                WL([ 'msg' => '订单金额异常', 'pay_money' => $order_info['pay_money'], 'total_fee' => $money],'wx_pay');
                return;
            }


            WL([ 'msg' => '---修改订单状态---'],'wx_pay');
            //开始修改订单状态，课程库存、课程销量
            Db::startTrans();

            $order_where = [
                ['order_id', '=', $order_info['order_id']],
                ['status', '=', 0],
            ];

            $update_order = [
                'status' => 1,
                'pay_time' => date('Y-m-d H:i:s'),
                'pay_voucher' => $data['transaction_id'],
            ];

            //修改订单状态
            $res = $orderModel->updateOrders($order_where, $update_order);
            WL([ 'msg' => $orderModel->getLastSql()],'wx_pay');
            if(empty($res))
            {
                WL([ 'msg' => '更新订单状态失败', 'order_id' => $order_info['order_id']],'wx_pay');
                Db::rollback();
                return;
            }

            WL([ 'msg' => '减少课程库存，增加课程销量'],'wx_pay');
            $course_info = $courseModel->getCourseInfoDetails($order_info['course_id'], 'id, title, inventory_number, sales_number,attend_type');
            WL([ 'msg' => $course_info],'wx_pay');
            //增加课程库存和销量
            $course_where = [
                ['id', '=', $order_info['course_id']],
            ];

            $inventory_number = $course_info['inventory_number'] - 1;
            $sales_number = $course_info['sales_number'] + 1;

            $update_course = [
                'inventory_number' => $inventory_number,
                'sales_number' => $sales_number,
            ];

            WL([ 'msg' => '开始更新课程'],'wx_pay');
            $res = $courseModel->updateCourse($course_where, $update_course);

            WL([ 'msg' => $courseModel->getLastSql()],'wx_pay');

            if(empty($res))
            {
                WL([ 'msg' => '更新订单对应的课程信息失败', 'course_id' => $order_info['course_id']],'wx_pay');
                Db::rollback();
                return;
            }

            //订单成功
            WL([ 'msg' => '订单支付成功，当前状态已发货', 'order_id' => $order_info['order_id']],'wx_pay');
            Db::commit();


            if($course_info['attend_type'] == 2)
            {
                //查找课程兑换码
                $date = date('Y-m-d H:i:s');
                $code_where = [
                    ['course_id', '=', $order_info['course_id']],
                    ['start_time', '<=', $date], 
                    ['end_time', '>=', $date],
                    ['status', '=', 1],
                    
                ];
                $code_info = $coursecodeModel->getCourseCodeInfo($code_where);
                //如果有兑换码，就开始绑定到当前订单上
                if(!empty($code_info))
                {
                    Db::startTrans();
                    //1.绑定到订单上
                    $order_code_where = [
                        ['order_id', '=', $order_info['order_id']],
                        ['status', '=', 1],
                    ];

                    $update_code_order = [
                        'status' => 2,
                        'dispatch_time' => date('Y-m-d H:i:s'),
                        'course_code_id' => $code_info['id'],
                    ];
                    $res = $orderModel->updateOrders($order_code_where, $update_code_order);
                    if(empty($res))
                    {
                        WL([ 'msg' => '订单发货失败', 'order_id' => $order_info['order_id']],'wx_pay');
                        //如果发货失败，等待定时任务，定时捞订单并发货。
                        Db::rollback();
                    }else{

                        //2.发货成功，修改兑换码状态
                        $code_where = [
                            ['id', '=', $code_info['id']],
                            ['course_id', '=', $code_info['course_id']],
                            ['status', '=', 1],
                            
                        ];

                        $code_update = [
                            'status' => 2,
                            'order_id' => $order_info['order_id'],
                            'issue_time' => date('Y-m-d H:i:s'),
                        ];
                        $res = $coursecodeModel->updateCourseCodeWhereId($code_where, $code_update);
                        if(empty($res))
                        {
                            WL([ 'msg' => '更新订单绑定的兑换码状态失败', 'order_id' => $order_info['order_id']],'wx_pay');
                            //如果发货失败，等待定时任务，定时捞订单并发货。
                            Db::rollback();
                        }else{
                             WL([ 'msg' => '订单发货成功，绑定兑换码OK', 'order_id' => $order_info['order_id']],'wx_pay');
                        }
                        Db::commit();
                    }
                }
            }
           

            WL([ 'msg' => '---订单支付成功---', 'order_id' => $order_info['order_id']],'wx_pay');


            //告诉微信，成功了
            $wx_msg = [
                'return_code' => 'SUCCESS',
                'return_msg' => 'OK',
            ];
            
            $res = $this->arrayToXml($wx_msg);
            return $res;

        }else{
            //回调付款失败，就记录日志
            WL([ 'msg' => '交易失败'],'wx_h5_pay');
            return;
        }
    }


    /*
    生成签名
    */
    protected function getSign2($Obj)
    {
        foreach ($Obj as $k => $v)
        {
            $Parameters[$k] = $v;
        }
        //签名步骤一：按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false, true);
        //echo "【string】 =".$String."</br>";
        //签名步骤二：在string后加入KEY
        $String = $String."&key=ce0bfd15059b68d67688884d7a3d3e8c";
//        echo "<textarea style='width: 50%; height: 150px;'>$String</textarea> <br />";
        //签名步骤三：MD5加密
        WL($String, 'sign');
        $result_ = strtoupper(md5($String));
        return $result_;
    }


    //将数组转成uri字符串
    protected function formatBizQueryParaMap($paraMap, $urlencode, $strtolower)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v)
        {
            if($urlencode)
            {
                $v = urlencode($v);
            }

            if($strtolower)
            {
                $buff .= $k . "=" . $v . "&";
            }else{
                $buff .= strtolower($k) . "=" . $v . "&";
            }
            
        }
        $reqPar;
        if (strlen($buff) > 0)
        {
            $reqPar = substr($buff, 0, strlen($buff)-1);
        }
        return $reqPar;
    }



    //数组转xml
    protected function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key=>$val)
        {
            if (is_numeric($val))
            {
                $xml.="<".$key.">".$val."</".$key.">";

            }
            else
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
        }
        $xml.="</xml>";
        return $xml;
    }
}